/**
 * 淹没分析
 */
import * as Cesium from "cesium";
// 淹没分析
export default class SubmergenceAnalysis {
    viewer : any
    isTerrain : any
    handler : any
    tempEntities : any
    polygonEntities : any
    linePositionList : []
    tempPoints : []
    extrudedHeight : any
    height_max : any
    height_min : any
    step : any
    // 默认是范围图/深度图
    map_type : any
    polygon_degrees : any
    speed : any
    timer: any

    /**
     * 实例化淹没分析
     * @param viewer
     * @param isTerrain 是否开启地形 true/false
     * @param height_max 最高高度
     * @param height_min 最低高度
     * @param step  每步增加高度
     * @param map_type 范围图，深度图，默认范围图true/false
     * @param positionsArr 坐标数组[lon1, lat1, lon2, lat2, ...]
     * @param speed 速度
     */
    constructor(viewer:any, isTerrain = true, height_max:any, height_min:any, step:any, map_type:any, positionsArr:any, speed = 1) {
        this.viewer = viewer
        this.isTerrain = isTerrain
        this.handler = null
        this.tempEntities = []
        this.polygonEntities = []
        this.linePositionList = []
        this.tempPoints = []
        this.extrudedHeight = height_min
        this.height_max = height_max
        this.height_min = height_min
        this.step = step
        // 默认是范围图/深度图
        this.map_type = map_type
        this.polygon_degrees = positionsArr
        this.speed = speed
        this.timer = ''
        //this._initViewStatus(this.viewer)
        this._addDisListener()
    }

    _initViewStatus(viewer: any) {
        var scene = viewer.scene
        scene.globe.depthTestAgainstTerrain = true
        viewer.camera.flyTo({
            //scene.camera.setView({
            // 摄像头的位置
            destination: Cesium.Cartesian3.fromDegrees(108.9, 34, 5000.0),
            orientation: {
                heading: Cesium.Math.toRadians(0.0),//默认朝北0度，顺时针方向，东是90度
                pitch: Cesium.Math.toRadians(-20),//默认朝下看-90,0为水平看，
                roll: Cesium.Math.toRadians(0)//默认0
            }
        });
        viewer.skyAtmosphere = false
    }
    // 根据矩形范围得到行列数点坐标和高程信息
    _getPoints(xmin: any, xmax: any, ymin: any, ymax: any) {
        const x_count = 10
        const y_count = 10
        let cartesians = new Array(x_count * y_count);
        const x_d = (xmax - xmin) / x_count
        for (var i = 0; i < x_count; ++i) {
            const start_pt = { x: xmin + i * x_d, y: ymax }
            const end_pt = { x: xmin + i * x_d, y: ymin }
            for (let j = 0; j < y_count; j++) {
                const offset = j / (y_count - 1);
                const x = Cesium.Math.lerp(start_pt.x, end_pt.x, offset);
                const y = Cesium.Math.lerp(start_pt.y, end_pt.y, offset);
                cartesians[j + i * y_count] = Cesium.Cartographic.fromDegrees(x, y);
            }
        }
        return cartesians

    }
    _getHeights(cartesians: any, extrudedHeight: any, callback: any) {
        var terrainProvider: any = new Cesium.createWorldTerrain({
            requestVertexNormals: true
        })
        // 根据地形计算某经纬度点的高度
        var promise = Cesium.sampleTerrainMostDetailed(terrainProvider, cartesians);
        promise.then(function (updatedPositions) {
            let positions: any = updatedPositions.filter(d => {
                const cartographic = d
                if (cartographic) {
                    const h_d = extrudedHeight - cartographic.height
                    return h_d > 0
                }
            })
            positions = positions.map((d: any) => {
                const cartographic = d
                let h = extrudedHeight - cartographic.height
                return {
                    x: Cesium.Math.toDegrees(cartographic.longitude),
                    y: Cesium.Math.toDegrees(cartographic.latitude),
                    value: h
                }

            })

            if (callback) {

                callback(positions)
            }
        })
    }

    _addDisListener() {
        let viewer = this.viewer
        let scene = viewer.scene
        let linePositionList = this.linePositionList
        viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)
        this.handler = new Cesium.ScreenSpaceEventHandler(scene.canvas)
        // 绘制线
        this._drawLine(linePositionList)
        //this.loadGrandCanyon()
        // 绘制面
        if (this.map_type) {
            this._drawPoly(this.polygon_degrees)
        } else {
            // 得到插值网格
            const bounds = {
                west: 115.8784,
                east: 115.9614,
                south: 39.9912,
                north: 40.0381
            }

            const positions_cartesian = this._getPoints(bounds.east, bounds.west, bounds.south, bounds.north)
            this._getHeights(positions_cartesian, this.extrudedHeight, (d) => {
                // this.heatMapObj = new HeatMap(this.viewer, d, bounds);
            })
        }

    }
    _reDraw() {
        this.tempPoints = []
        this.linePositionList.length = 0
        // this.areaPositionList.length = 0
        for (let entity of this.tempEntities) {
            this.viewer.entities.remove(entity)
        }
        this.tempEntities = []
    }

    _drawLine(linePositionList: any) {
        let lineStyle = {
            width: 2,
            material: Cesium.Color.CHARTREUSE
        }

        let entity = this.viewer.entities.add({
            polyline: lineStyle,
        })

        entity.polyline.positions = new Cesium.CallbackProperty(function () {
            return linePositionList
        }, false)

        this.polygonEntities.push(entity)
    }
    _drawPoint(point_Cartesian3: any) {
        let entity =
            this.viewer.entities.add({
                position: point_Cartesian3,
                point: {
                    pixelSize: 10,
                    color: Cesium.Color.GOLD,
                    // disableDepthTestDistance: Number.POSITIVE_INFINITY,
                    // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
                }
            })
        this.tempEntities.push(entity)
    }


    _drawPoly(degrees: any) {
        const that = this
        let entity =
            this.viewer.entities.add({
                polygon: {
                    hierarchy: {},
                    material: new Cesium.Color.fromBytes(64, 157, 253, 100),
                    perPositionHeight: true,

                }
            })
        entity.polygon.hierarchy = new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(degrees))
        entity.polygon.extrudedHeight = new Cesium.CallbackProperty(() => that.extrudedHeight, false)
        this.polygonEntities.push(entity)
    }

    // 世界坐标转经纬坐标
    _car3ToLatLon(cartesian: any) {
        let cartographic = Cesium.Cartographic.fromCartesian(cartesian)
        let longitudeString = Cesium.Math.toDegrees(cartographic.longitude)
        let latitudeString = Cesium.Math.toDegrees(cartographic.latitude)
        return {
            lon: longitudeString,
            lat: latitudeString,
            height: cartographic.height
        }
    }

    //移除整个资源
    remove() {
        let viewer = this.viewer
        for (let tempEntity of this.tempEntities) {
            viewer.entities.remove(tempEntity)
        }
        for (let lineEntity of this.polygonEntities) {
            viewer.entities.remove(lineEntity)
        }
        this.handler.destroy()
    }
    start() {
        const that = this
        this.timer = window.setInterval(() => {
            if ((that.height_max > that.extrudedHeight) && (that.extrudedHeight >= that.height_min)) {
                that.extrudedHeight = that.extrudedHeight + that.step
            }
        }, that.speed * 1000)
        if (that.map_type) {
            that._drawPoly(that.polygon_degrees)
        } else {
            // if (this.heatMapObj) { }

        }

    }
    clear() {
        let viewer = this.viewer
        if (this.timer) {
            window.clearInterval(this.timer)
            this.timer = null
        }
        this.extrudedHeight = this.height_min;
        // if (this.heatMapObj)
        //     this.heatMapObj.show(false)
        for (let entity of this.polygonEntities) {
            viewer.entities.remove(entity)
        }
        viewer.skyAtmosphere = true;
    }
}
